//
//  AppDelegate.swift
//  GuMro
//
//  Created by mac on 2019/12/3.
//  Copyright © 2019 cn.gomro.app. All rights reserved.
//

import UIKit
import SnapKit
import Alamofire
import IQKeyboardManagerSwift


@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
    
    //MARK: - proterty
    public static var netWorkType:String?
    
    /** 单例对象 */
    private static let _app:AppDelegate = AppDelegate.init()
    public static func app() -> AppDelegate {
        return _app
    }
    
    
    //MARK: - override func
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        // Override point for customization after application launch.
        
        //网络监测
        DispatchQueue.global().async {
            self.netWorkCheck()
        }
        
        //第三方库初始化
        DispatchQueue.main.async {
            autoreleasepool {
                self.initThird()
            }
        }
        
        //启动图动画
        self.startAnimation()
        
        // [S] 开启数据库
        DispatchQueue.global().async {
            FMDBUtils.shareInstance.initDBAndTables()
        }
        // [E] 开启数据库
        
        //输出异常日志
        CrashHandler.setup {[weak self] (stackTrace, completion) in
            self?.showExceptionFor(Reason: stackTrace)
            completion()
        }
        
        return true
    }
    
    func applicationWillResignActive(_ application: UIApplication) {
        // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
        // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
    }
    
    func applicationDidEnterBackground(_ application: UIApplication) {
        // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
        // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
    }
    
    func applicationWillEnterForeground(_ application: UIApplication) {
        // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
    }
    
    //已经进入前台
    func applicationDidBecomeActive(_ application: UIApplication) {
        // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
    }
    
    
    //MARK: - 程序将终止
    func applicationWillTerminate(_ application: UIApplication) {
        // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
        
        print("applicationWillTerminate:程序将终止")
        self.clearInfo()
    }
    
    deinit {
        self.clearInfo()
        NetworkReachabilityManager.default?.stopListening()
        print("\(String(describing: self.className())) 已销毁")
    }
    
    
    //MARK: - lazy load
    /** UIWindow */
    lazy var window: UIWindow? = {
        autoreleasepool {
            // [S] 设置App 主容器
            let _winDown = UIWindow.init(frame: UIScreen.main.bounds)
            _winDown.backgroundColor = Setting.K_APP_VIEWCONTROLLER_BACKGROUND_COLOR
            _winDown.rootViewController = self.navController
            
            //设置系统主题色
            if #available(iOS 7.0, *) {
                //tint color 为 高亮颜色
                //tint color默认是蓝色，但是通过改变它的颜色你可以立即让app获得自己独特风格
                _winDown.tintColor = Setting.K_APP_TINT_COLOR
            }
            // [S] 设置App 主容器
            
            _winDown.makeKeyAndVisible()
            _winDown.makeKey()
            return _winDown
        }
    }()
    
    private lazy var navController:BaseNavigationController = {
        let _navigation = BaseNavigationController.init(rootViewController: BaseTabBarController.init())
        return _navigation
    }()
}


//MARK: - Class custom method
extension AppDelegate {
    
    private func initThird(){
        //IQKeyboardManager 启用
        IQKeyboardManager.shared.enable = true
        IQKeyboardManager.shared.shouldResignOnTouchOutside = true
        
        // 控制键盘上的工具条文字颜色是否用户自定义
        IQKeyboardManager.shared.shouldToolbarUsesTextFieldTintColor = true
        // 有多个输入框时，可以通过点击Toolbar 上的“前一个”“后一个”按钮来实现移动到不同的输入框
        IQKeyboardManager.shared.toolbarManageBehaviour = .bySubviews
        // 控制是否显示键盘上的工具条
        IQKeyboardManager.shared.enableAutoToolbar = true
        // 是否显示占位文字
        IQKeyboardManager.shared.shouldShowToolbarPlaceholder = true
        // 设置占位文字的字体
        IQKeyboardManager.shared.placeholderFont = UIFont.boldSystemFont(ofSize: 17)
        // 输入框距离键盘的距离
        IQKeyboardManager.shared.keyboardDistanceFromTextField = 10.0
        
        IQKeyboardManager.shared.registerTextFieldViewClass(YYTextView.classForCoder() as! UIView.Type,
                                                            didBeginEditingNotificationName: NSNotification.Name.YYTextViewTextDidBeginEditing.rawValue,
                                                            didEndEditingNotificationName: NSNotification.Name.YYTextViewTextDidEndEditing.rawValue)
        
        //SVProgressHUD
        SVProgressHUD.dismissLoading(isInit: true)
        
    }
    
    
    /**
     * 是否有网
     * @return true 有网 false 没网
     */
    func isNetWork() -> Bool {
        return NetworkReachabilityManager.default?.isReachable ?? false
    }
    
    //网络监测
    private func netWorkCheck(){
        NetworkReachabilityManager.default?.startListening(onUpdatePerforming: { status in
            switch(status){
            case .notReachable:
                AppDelegate.netWorkType = "没有网络"
                print("没有网络")
                SVProgressHUD.showInfo(withStatus: "世上最遥远的距离,就是没有网(〒︿〒)")
                
                DispatchQueue.main.async {
                    //发送本地通知，方便后面使用
                    NotificationCenter.default.post(name: NSNotification.Name(rawValue: Setting.K_APP_IS_NET_WORK),
                                                    object: nil,
                                                    userInfo: [Setting.K_APP_IS_NET_WORK_CODE:404,"type":"网络有些问题，请检查"])
                }
                
            case .reachable(.cellular):
                print("蜂窝网络")
                AppDelegate.netWorkType = "蜂窝网络"
            case .reachable(.ethernetOrWiFi):
                print("Wifi或以太网")
                AppDelegate.netWorkType = "Wifi或以太网"
            default:
                print("未知网络")
                AppDelegate.netWorkType = "未知网络"
                break
            }
            
            if status != .notReachable {
                //发送本地通知，方便后面使用
                NotificationCenter.default.post(name: NSNotification.Name(rawValue: Setting.K_APP_IS_NET_WORK),
                                                object: nil,
                                                userInfo: [Setting.K_APP_IS_NET_WORK_CODE:200,"type":(AppDelegate.netWorkType ?? "未知网络") as Any])
            }
        })
    }
    
    /** 启动图动画 */
    private func startAnimation(){
        
        let infoDictionary:[String:Any] = Bundle.main.infoDictionary!
        let strStoryboardName:String = String.init(format:"%@",infoDictionary["UILaunchStoryboardName"] as! CVarArg)
        
        let storyboard:UIStoryboard = UIStoryboard.init(name: strStoryboardName, bundle: nil)
        let viewController:UIViewController = storyboard.instantiateViewController(withIdentifier: "LaunchScreen")
        
        var launchView:UIView? = viewController.view
        if launchView != nil {
            autoreleasepool {
                self.window?.addSubview(launchView!)
                
                //执行动画
                UIView.animate(withDuration: 1, animations: {
                    launchView?.alpha = 0.85
                    
                    //图片变大为原来的1.3倍
                    launchView?.transform = CGAffineTransform(scaleX: 1.3, y: 1.3)
                }) { (result:Bool) in
                    
                    //动画结束，移除imageView，呈现主界面
                    launchView?.removeFromSuperview()
                    
                    if result {
                        launchView = nil
                    }
                }
            }
        }
    }
    
    func enterMainApp(){
        
        UIApplication.shared.keyWindow!.rootViewController?.modalTransitionStyle = .flipHorizontal
        UIView.transition(with: UIApplication.shared.keyWindow!,
                          duration: 0.9,
                          options: UIView.AnimationOptions.transitionFlipFromLeft,
                          animations: {[weak self] in
            guard let self = self else { return }
            
            let oldState:Bool = UIView.areAnimationsEnabled
            UIView.setAnimationsEnabled(false)
            
            UIApplication.shared.keyWindow!.rootViewController?.dismiss(animated: false, completion: {
                print("rootViewController 已移除")
            })
            
            UIApplication.shared.keyWindow?.rootViewController?.removeFromParent()
            UIApplication.shared.keyWindow?.rootViewController = nil
            UIApplication.shared.keyWindow?.rootViewController = self.navController
            
            UIView.setAnimationsEnabled(oldState)
        }, completion: { (result:Bool) in
            //关闭键盘
            UIApplication.shared.keyWindow?.endEditing(true)
            
            //self.setShoppingCarFor(ViewController: UIApplication.shared.keyWindow!.rootViewController!)
            print("进入主程序")
        })
        
    }
    
    
    //MARK: - 远程通知相关事件
    /** 注册 deviceToken */
    func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
        
        let characterSet = CharacterSet(charactersIn: "<>")
        let nsdataStr = NSData.init(data: deviceToken)
        let deviceStr = nsdataStr.description.trimmingCharacters(in: characterSet).replacingOccurrences(of: " ", with: "")
        
        //融云推送
        //...
        
        print("DeviceToken:\(deviceStr)")
    }
    
    func application(_ application: UIApplication, didRegister notificationSettings: UIUserNotificationSettings) {
        // register to receive notifications
        application.registerForRemoteNotifications()
    }
    
    //iOS10以下使用这个方法接收通知
    func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any]) {
        print("推送信息：\(userInfo)")
    }
    
    //MARK: - 应用交互处理(外部应用打开app处理、支付、分享等)
    func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
        
        
        //url.path.lastPathComponent:文件名 数学七年级(上册)-1.zip
        //url.pathExtension：文件后缀 zip
        //url.path: 文件路径 /private/var/mobile/Containers/Data/Application/20E43B57-2BF3-45C9-B122-24D15D409622/Documents/Inbox/数学七年级(上册)-1.zip
        
        print(String.init(format:"isFire:%@,path:%@",url.isFileURL ? "是":"否",url.path))
        
        return true
    }
    
    
}


//MARK: - UNUserNotificationCenterDelegate
extension AppDelegate : UNUserNotificationCenterDelegate {
    
    @available(iOS 10.0, *)
    func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
        
        let userInfo:[String:Any] = response.notification.request.content.userInfo as! [String : Any]
        if response.notification.request.trigger!.isKind(of: UNPushNotificationTrigger.classForCoder()) {
            //应用处于后台时的远程推送接受
        }
        else{
            //应用处于后台时的本地推送接受
            print("应用处于后台时的本地推送接受")
        }
    }
    
    @available(iOS 10.0, *)
    func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
        
        let userInfo:[String:Any] = notification.request.content.userInfo as! [String : Any]
        
        if notification.request.trigger!.isKind(of: UNPushNotificationTrigger.classForCoder()) {
            
            //应用处于前台时的远程推送接受
        }
        else {
            //应用处于前台时的本地推送接受
            print("应用处于前台时的本地推送接受")
        }
        
        //当应用处于前台时提示设置，需要哪个可以设置哪一个
        completionHandler([.sound,.badge,.alert])
    }
    
}


//MARK: -
extension AppDelegate {
    
    //MARK: 移除
    private func clearInfo(){
        NotificationCenter.default.removeObserverBlocks()
        NotificationCenter.default.removeAssociatedValues()
        
        print("AppDelegate 已销毁")
    }
    
    
    //MARK: 异常处理
    private func showExceptionFor(Reason reason:String,
                                  andTitle t:String = "app异常"){
        
        let currentRunloop = CFRunLoopGetCurrent()
        
        if let vc = UIApplication.shared.keyWindow?.rootViewController {
            Utils.shareInstance().showBoxFor(ViewController: vc,
                                             andMessage: t,
                                             andOK: "提交日志,并返回首页",
                                             andOKBlock: { action in
                //异步提交异常日志
                //...
                
                //返回首页
                var arr = self.navController.popToRootViewController(animated: false)
                Utils.shareInstance().gotoRoot(ViewController: arr)
                arr?.removeAll()
                arr = nil
            },
                                             andCancle: nil,
                                             withInfo: reason)
        }
        
        if let arrModes = CFRunLoopCopyAllModes(currentRunloop) as? Array<CFString> {
            while true {
                for model in arrModes {
                    CFRunLoopRunInMode(CFRunLoopMode.init(rawValue: model), 0.001, false)
                }
            }
        }
    }
}
